package com.chiyoyo.shiro.framework;

import com.chiyoyo.tokenhelper.LoginInfoDTO;
import com.chiyoyo.tokenhelper.TokenHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.Set;

/**
 * @author chil
 * @since 2024/8/6
 * 自定义 Realm
 */
@Slf4j
public class MyRealm extends AuthorizingRealm {

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof MyAuthenticationToken;
    }

    /**
     * 重写父类方法，用于获取用户认证信息
     *
     * @param authenticationToken 认证令牌，包含了用户身份信息和凭证信息
     * @return 返回用户的认证信息，包括用户主体、凭证信息和领域名
     * @throws AuthenticationException 如果认证失败，则抛出认证异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        MyAuthenticationToken token = (MyAuthenticationToken) authenticationToken;
        String tokenValue = token.getValue();
        if (TokenHelper.isLogin(tokenValue)) {
            TokenHelper.refresh(tokenValue);
            return new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());
        } else {
            throw new AuthenticationException(String.format("用户认证失败: 无效的 Token: %s", tokenValue));
        }
    }

    /**
     * 重写父类方法，用于获取用户授权信息
     *
     * @param principalCollection 用户主体信息集合
     * @return 返回用户的授权信息，包括角色和权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        try {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

            if (principalCollection == null) {
                log.warn("用户授权失败: PrincipalCollection 为空");
                return info;
            }

            String token = (String) principalCollection.getPrimaryPrincipal();
            LoginInfoDTO loginInfo = TokenHelper.getLoginInfo(token);
            if (loginInfo != null) {
                Set<String> perms = loginInfo.getPerms();
                info.addStringPermissions(perms);
            } else {
                log.warn("用户授权失败: 未找到登录信息");
            }
            return info;
        } catch (Throwable throwable) {
            log.error("用户授权异常", throwable);
            throw new AuthorizationException(throwable);
        }
    }
}
